#include "input.h"

TIM_HandleTypeDef TIM5_Handler;	// 定时器5句柄


/***************************
* 函数名： TIM5_CH1_Input_Init
* 功能：LED初始化函数
* 输入：arr：自动重装载值（TIM5是16位！！）
*				psc：时钟预分频
* 输出：无
*/
void TIM5_CH1_Input_Init(u32 arr,u16 psc)
{
	TIM_IC_InitTypeDef TIM5_CH1Config;
	
	TIM5_Handler.Instance = TIM5;												// 通用定时器5
	TIM5_Handler.Init.Prescaler = psc;									// 分频系数
	TIM5_Handler.Init.CounterMode = TIM_COUNTERMODE_UP;	// 向上计数器
	TIM5_Handler.Init.Period = arr;											// 自动装载值
	TIM5_Handler.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;	// 时钟分频因子
	HAL_TIM_IC_Init(&TIM5_Handler);											// 初始化输入捕获时机参数
	
	TIM5_CH1Config.ICPolarity = TIM_ICPOLARITY_RISING;								// 上升沿捕获
	TIM5_CH1Config.ICSelection = TIM_ICSELECTION_DIRECTTI; 						// 映射到TT1上
	TIM5_CH1Config.ICPrescaler = TIM_ICPSC_DIV1;											// 配置输入分频，不分频
	TIM5_CH1Config.ICFilter = 0;																			// 配置输入滤波器，不滤波
	HAL_TIM_IC_ConfigChannel(&TIM5_Handler,&TIM5_CH1Config,TIM_CHANNEL_1); // 配置TIM5通道1
	HAL_TIM_IC_Start_IT(&TIM5_Handler,TIM_CHANNEL_1);									// 开启TIM5捕获通道1，且开启捕获中断
	__HAL_TIM_ENABLE_IT(&TIM5_Handler,TIM_IT_UPDATE);									// 使能更新中断
	
}

/*************************************
* 定时器5底层驱动，时钟使能，引脚配置
* 该函数被HAL_TIM_IC_Init()调用
* htim：定时器5句柄
*************************************/
void HAL_TIM_IC_MspInit(TIM_HandleTypeDef *htim)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	__HAL_RCC_TIM5_CLK_ENABLE();										// 使能TIM5时钟
	__HAL_RCC_GPIOA_CLK_ENABLE();										// 使能GPIOA时钟
	
	GPIO_InitStructure.Pin = GPIO_PIN_0;						// PA0
	GPIO_InitStructure.Mode = GPIO_MODE_AF_INPUT;		// 利用推挽输入
	GPIO_InitStructure.Pull = GPIO_PULLDOWN;				// 下拉
	GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH; // 高速
	HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	HAL_NVIC_SetPriority(TIM5_IRQn,2,0);						// 设置中断优先级，抢占优先级2，子优先级0
	HAL_NVIC_EnableIRQ(TIM5_IRQn);									// 开启TIM5中断通道
}

/****************************************
* 捕获状态：
* [7]：0，没有成功捕获，1成功捕获一次
* [6]：0，还没捕获到高电平，1已捕获到高电平
* [5]：捕获高平后溢出的次数（对于32位定时器来说，1us计数器加1，溢出时间：4294秒）
****************************************/
u8 TIM5_CH1_CAPTURE_STA = 0;			// 输入捕获状态
u32 TIM5_CH1_CAPTURE_VAL;					// 输入捕获值(TIM2/TIM5是32位)

// 定时器5中断服务函数
void TIM5_IRQHandler(void)
{
	HAL_TIM_IRQHandler(&TIM5_Handler);
}

/*************************************
* 定时器更新中断（计数溢出）中断处理回
* 调函数，该函数在HAL_TIM_IRQHandler中
* 被调用
**************************************/
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	if((TIM5_CH1_CAPTURE_STA & 0x80) == 0) // 还未捕获成功
	{
		if(TIM5_CH1_CAPTURE_STA & 0x40) // 已捕获到高电平
		{
			if((TIM5_CH1_CAPTURE_STA & 0x3F) == 0x3F) // 高电平太长了
			{
				TIM5_CH1_CAPTURE_STA |= 0x80;					// 标记成功捕获一次
				TIM5_CH1_CAPTURE_VAL = 0xFFFF;
			}
			else
			{
				TIM5_CH1_CAPTURE_STA++;
			}
		}
	}
}

/***********************************************************
* 定时器输入捕获中断处理回调函数，该函数在HAL_TIM_IRQHandler
* 中被调用
************************************************************/
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
	if((TIM5_CH1_CAPTURE_STA & 0x80) == 0) // 还未成功捕获
	{
		if(TIM5_CH1_CAPTURE_STA & 0x40) // 捕获到一个下降沿
		{
			TIM5_CH1_CAPTURE_STA |= 0x80;						// 标记成功捕获一次高电平脉宽
			TIM5_CH1_CAPTURE_VAL = HAL_TIM_ReadCapturedValue(&TIM5_Handler, TIM_CHANNEL_1); // 获取当前捕获值
			TIM_RESET_CAPTUREPOLARITY(&TIM5_Handler,TIM_CHANNEL_1);			// 一定要先清除原来的设置
			TIM_SET_CAPTUREPOLARITY(&TIM5_Handler,TIM_CHANNEL_1,TIM_ICPOLARITY_RISING); // 配置TIM5通道1上升沿捕获
		}
		else
		{
			TIM5_CH1_CAPTURE_STA = 0;						// 清空
			TIM5_CH1_CAPTURE_VAL = 0;
			TIM5_CH1_CAPTURE_STA |= 0x40;				// 标记捕获到了上升沿
			__HAL_TIM_DISABLE(&TIM5_Handler);		// 关闭定时器5
			__HAL_TIM_SET_COUNTER(&TIM5_Handler,0);
			TIM_RESET_CAPTUREPOLARITY(&TIM5_Handler,TIM_CHANNEL_1); // 一定要先清除原来的设置
			TIM_SET_CAPTUREPOLARITY(&TIM5_Handler,TIM_CHANNEL_1,TIM_ICPOLARITY_FALLING); // 定时器5通道1设置下为降沿捕获
			__HAL_TIM_ENABLE(&TIM5_Handler); // 使能定时器5
		}
	}
}